﻿/*
 * udpserverdevice.cpp
 *
 *  Created on: 2017年2月23日
 *      Author: work
 */

#include <dm/export.hpp>

#define DM_API_OS_COM DM_API_EXPORT

#include <dm/os/com/udpserverdevice.hpp>
#include <dm/os/log/logger.hpp>

namespace dm{
namespace os{
namespace com{

static const char* logModule = "CUdpServerDevice.com.os.dm";

using namespace boost::asio;

CUdpServerDevice::CUdpServerDevice( ios_t& ios,const size_t& rxBufSize ):
		CDevice(rxBufSize),m_dev(ios){
	log().debug(THISMODULE "创建对象");
}

CUdpServerDevice::~CUdpServerDevice(){
	log().debug(THISMODULE "销毁对象");
	m_dev.shutdown(m_dev.shutdown_both);
	m_dev.close();
}

void CUdpServerDevice::setDest( const char* host,const short& port ){
	log().debug(THISMODULE "设置目的地址:%s:%d",host,port);
	m_dest.address( ip::address::from_string(host));
	m_dest.port(port);
}

void CUdpServerDevice::setDest( const end_t& dest ){
	m_dest = dest;
}

bool CUdpServerDevice::asynConnect(){
	if( m_state==Unconnected ){
		if( startConnect() ){
			m_state = Connecting;
			handler_connect();
			return true;
		}
	}

	return false;
}

void CUdpServerDevice::onReceived( const dm::uint8* buf,const size_t& len ){
	onReceived(m_peer,buf,len);
}

void CUdpServerDevice::onReceived( const end_t& peer,const uint8* /*buf*/,const size_t& /*len*/ ){
	log().debug(THISMODULE "设置目标地址为对端地址%s:%d,并发送hello",peer.address().to_string().c_str(),peer.port());
	setDest(peer);
	asynSend((const dm::uint8*)"hello",6);
}

bool CUdpServerDevice::checkAndSetAddress( const CUdpServerAddr& addr ){
	log().debug(THISMODULE "设置地址%s",addr.toString().c_str());
	m_addr = addr;
	return true;
}

bool CUdpServerDevice::startConnect(){
	const CUdpServerAddr* addr = m_addr.asUdpServer();
	if( !addr ){
		log().warnning(THISMODULE "没有可用地址");
		return false;
	}

	m_dev.open(ip::udp::v4());
	m_dev.set_option(ip::udp::socket::reuse_address(true));
	end_t local(ip::address::from_string(addr->getLocalHost().c_str()),addr->getLocalPort());
	m_dev.bind(local);

	return true;
}

bool CUdpServerDevice::stopConnect(){
	m_dev.close();
	handler_disconnect();
	return true;
}

bool CUdpServerDevice::startSend( const dm::uint8* buf,const size_t& len ){
	try{
		m_dev.async_send_to( buffer(buf,len),m_dest,
				boost::bind(&CUdpServerDevice::handler_tx,this,placeholders::error)
		);
	}catch( std::exception& e ){
		log().warnning(THISMODULE "发送数据失败，可能是未设置目的地址,%s",e.what());
		return false;
	}
	return true;
}

void CUdpServerDevice::start_rx(){
	m_dev.async_receive_from( buffer(m_rxBuf.get(),m_rxBufSize),m_peer,
			boost::bind(&CUdpServerDevice::handler_rx,this,
					placeholders::error,
					placeholders::bytes_transferred)
	);
}

void CUdpServerDevice::cancelDev(){
	m_dev.cancel();
}

}
}
}


